/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include "stdio.h"

#include "thread.hpp"
#include "ticks.hpp"
#include <iostream>

#include "log.h"

using namespace cpp_freertos;
using namespace std;

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
osThreadId defaultTaskHandle;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void const * argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
extern "C" void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  /* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */


class DefaultThread : public Thread {
public:
	DefaultThread(int id, string name, uint16_t stackSize=256, int priority=1, uint32_t delay_ms=1000)
    	: Thread(name, (UBaseType_t)stackSize, priority),
		  DelayInMs(delay_ms),
		  Id(id)
	{
		//
		//  Now that construction is completed, we
		//  can safely start the thread.
		//
		Start();
	};
protected:
	virtual void Run() {
		while (true) {
			TickType_t ticks = Ticks::MsToTicks(DelayInMs);
			Delay(ticks);
			info_log("Running thread %s\r\n", GetName().c_str());
			//std::cout << "test" << std::endl; //endl只输出\n
			std::cout << "test\r\n";
		}
	};

private:
	int DelayInMs;
	int Id;
};

class TEST
{
public:
        TEST():a(0),b(0){};
        TEST(int x,int y):a(x),b(y){};

        int sum(int a, int b)
        {
                return a+b;
        }
private:
        int a;
        int b;
};

class Machine: public DefaultThread
{
public:
	Machine();
	TEST test{100,200};

	DefaultThread test1_thread{1, "test1", 512, 1, 500};
	DefaultThread test2_thread{2, "test2", 512, 1};
	DefaultThread test3_thread{3, "test3"};
#if 1
	static Machine &instance();
#else
	static Machine &instance()
	{
		static Machine ins;
		return ins;
	}
#endif
private:
	int m_value;
};

Machine::Machine()
:DefaultThread(0, "default", 512, 1, 500),
 m_value(80)
{

}

Machine& Machine::instance()
{
	static Machine ins;

	return ins;
}

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  //osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  //defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */

  Machine::instance();//实例化

#if 1 //malloc test
  int *pt = new int[0x1000];
  if(pt == NULL)
  {
	  printf("new[] fail\r\n");
  }
  delete []pt;

  pt = (int *)malloc(sizeof(int)*0x1500);
  if(pt == NULL)
  {
    printf("malloc fail\r\n");
  }
  free(pt);
#endif

  Thread::StartScheduler();

  /* USER CODE END RTOS_THREADS */

}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */
